package storage_define

import (
	"fmt"
	"github.com/google/uuid"
	"go-iot-gateway/internal/apk/binarys"
	"go-iot-gateway/internal/apk/types"
	"go-iot-gateway/internal/conf_table/define"
	"time"
)

const (
	QOS_GOOD = 0
	QOS_INIT = 50
	QOS_BAD  = 100
)

// 值对象
type ValObject interface {
	Id() string
	//值名称
	TagName() string
	//值
	Val() interface{}
	//数据类型
	DataType() string
	//时间戳
	Ts() int64
	//品质: 0 好 , 100 坏 ， 50 初始化中
	Qos() uint8
	//值个数
	Size() int
	//设值与时间
	SetTs(ts int64) ValObject
	//设置质量
	SetQos(uint82 uint8) ValObject
	//设值
	SetBytes(bytes []byte, dataFormat string) error
	//设值
	SetVal(val interface{}) error
}

//todo 批值对象

// ====== 空值 ===========
type NilVal struct {
	id       string
	tagName  string
	dataType string
	qos      uint8
	ts       int64
}

func (b *NilVal) Size() int {
	return 1
}

func (b *NilVal) String() string {
	date := time.UnixMilli(b.Ts()).Format("2006-01-02 15:04:05")
	return fmt.Sprintf("| Name: %-17v  Val: %-14v  Qos: %-5v  Ts: %-12v|", b.TagName(), b.Val(), b.Qos(), date)
}

func (b *NilVal) Id() string {
	return b.id
}

func (b *NilVal) TagName() string {
	return b.tagName
}

func (b *NilVal) Val() interface{} {
	return nil
}

func (b *NilVal) DataType() string {
	return b.dataType
}

func (b *NilVal) Qos() uint8 {
	return b.qos
}

func (b *NilVal) Ts() int64 {
	return b.ts
}

func (b *NilVal) SetTs(ts int64) ValObject {
	b.ts = ts
	return b
}

func (b *NilVal) SetQos(qos uint8) ValObject {
	b.qos = qos
	return b
}

func (b *NilVal) SetBytes(bytes []byte, dataFormat string) error {
	panic("无法设值Nil")
}

func (b *NilVal) SetVal(val interface{}) error {
	panic("无法设值Nil")
}

// =========== Uint64值对象类型  =============
type Uint64Val struct {
	NilVal
	val uint64
}

func (b *Uint64Val) String() string {
	date := time.UnixMilli(b.Ts()).Format("2006-01-02 15:04:05")
	return fmt.Sprintf("| Name: %-17v  Val: %-14v  Qos: %-5v  Ts: %-12v|", b.TagName(), b.Val(), b.Qos(), date)
}

func (b *Uint64Val) Uint64Val() uint64 {
	return b.val
}

func (b *Uint64Val) SetUint64Val(val uint64) {
	b.val = val
}

func (b *Uint64Val) Val() interface{} {
	return b.val
}

func (b *Uint64Val) DataType() string {
	return conf_table_define.DATA_TYPE_UINT64
}

func (b *Uint64Val) SetBytes(bytes []byte, dataFormat string) error {
	b.val = binarys.BytesToUint64(bytes, dataFormat)
	return nil
}

func (b *Uint64Val) SetVal(val interface{}) error {
	toInt64, err := types.ToUint64(val)
	if err != nil {
		return err
	}
	b.val = toInt64
	return nil
}

// =========== int64值对象类型  =============
type Int64Val struct {
	NilVal
	val int64
}

func (b *Int64Val) String() string {
	date := time.UnixMilli(b.Ts()).Format("2006-01-02 15:04:05")
	return fmt.Sprintf("| Name: %-17v  Val: %-14v  Qos: %-5v  Ts: %-12v|", b.TagName(), b.Val(), b.Qos(), date)
}

func (b *Int64Val) Int64Val() int64 {
	return b.val
}

func (b *Int64Val) SetInt64Val(val int64) {
	b.val = val
}

func (b *Int64Val) Val() interface{} {
	return b.val
}

func (b *Int64Val) DataType() string {
	return conf_table_define.DATA_TYPE_INT64
}

func (b *Int64Val) SetBytes(bytes []byte, dataFormat string) error {
	b.val = binarys.BytesToInt64(bytes, dataFormat)
	return nil
}

func (b *Int64Val) SetVal(val interface{}) error {
	toInt64, err := types.ToInt64(val)
	if err != nil {
		return err
	}
	b.val = toInt64
	return nil
}

// ============= float64值对象类型  =============
type Float64Val struct {
	NilVal
	val float64
}

func (b *Float64Val) String() string {
	date := time.UnixMilli(b.Ts()).Format("2006-01-02 15:04:05")
	return fmt.Sprintf("| Name: %-17v  Val: %-14v  Qos: %-5v  Ts: %-12v|", b.TagName(), b.Val(), b.Qos(), date)
}

func (b *Float64Val) Float64Val() float64 {
	return b.val
}

func (b *Float64Val) SetFloat64Val(val float64) {
	b.val = val
}

func (b *Float64Val) Val() interface{} {
	return b.val
}

func (b *Float64Val) DataType() string {
	return conf_table_define.DATA_TYPE_FLOAT64
}

func (b *Float64Val) SetBytes(bytes []byte, dataFormat string) error {
	b.val = binarys.BytesToFloat64(bytes, dataFormat)
	return nil
}

func (b *Float64Val) SetVal(val interface{}) error {
	toFloat64, err := types.ToFloat64(val)
	if err != nil {
		return err
	}
	b.val = toFloat64
	return nil
}

// ============ 字符串对象 ===============
type StringVal struct {
	NilVal
	val string
}

func (b *StringVal) String() string {
	date := time.UnixMilli(b.Ts()).Format("2006-01-02 15:04:05")
	return fmt.Sprintf("| Name: %-17v  Val: %-14v  Qos: %-5v  Ts: %-12v|", b.TagName(), b.Val(), b.Qos(), date)
}

func (b *StringVal) StringVal() string {
	return b.val
}

func (b *StringVal) SetStringVal(val string) {
	b.val = val
}

func (b *StringVal) Val() interface{} {
	return b.val
}

func (b *StringVal) DataType() string {
	return conf_table_define.DATA_TYPE_STRING
}

func (b *StringVal) SetBytes(bytes []byte, dataFormat string) error {
	b.val = binarys.BytesToString(bytes)
	return nil
}

func (b *StringVal) SetVal(val interface{}) error {
	b.val = fmt.Sprintf("%+v", val)
	return nil
}

//============ 实例化 ===============

func NewNilVal(tag *conf_table_define.TagInfo) *NilVal {
	return &NilVal{
		id:       uuid.New().String(),
		tagName:  tag.Tag_name,
		dataType: tag.DataTypeStr(),
		ts:       time.Now().UnixMilli(),
		qos:      QOS_GOOD,
	}
}

func NewNilValII(tagName string, dataType string, ts int64, qos uint8) *NilVal {
	return &NilVal{
		id:       uuid.New().String(),
		tagName:  tagName,
		dataType: dataType,
		ts:       ts,
		qos:      qos,
	}
}

func NewStringVal(tagName string, val string, ts int64, qos uint8) *StringVal {
	return &StringVal{
		val: val,
		NilVal: NilVal{
			id:       uuid.New().String(),
			tagName:  tagName,
			dataType: conf_table_define.DATA_TYPE_STRING,
			ts:       ts,
			qos:      qos,
		},
	}
}

func NewFloat64Val(tagName string, val float64, ts int64, qos uint8) *Float64Val {
	return &Float64Val{
		val: val,
		NilVal: NilVal{
			id:       uuid.New().String(),
			tagName:  tagName,
			dataType: conf_table_define.DATA_TYPE_FLOAT64,
			ts:       ts,
			qos:      qos,
		},
	}
}

func NewInt64Val(tagName string, val int64, ts int64, qos uint8) *Int64Val {
	return &Int64Val{
		val: val,
		NilVal: NilVal{
			id:       uuid.New().String(),
			tagName:  tagName,
			dataType: conf_table_define.DATA_TYPE_INT64,
			ts:       ts,
			qos:      qos,
		},
	}
}

func NewUint64Val(tagName string, val uint64, ts int64, qos uint8) *Uint64Val {
	return &Uint64Val{
		val: val,
		NilVal: NilVal{
			id:       uuid.New().String(),
			tagName:  tagName,
			dataType: conf_table_define.DATA_TYPE_INT64,
			ts:       ts,
			qos:      qos,
		},
	}
}

func NewValObject(tag *conf_table_define.TagInfo) ValObject {
	switch tag.Data_type {
	case conf_table_define.INT8, conf_table_define.INT16, conf_table_define.INT32, conf_table_define.INT64,
		conf_table_define.BCD16, conf_table_define.BCD32:
		int64Val := &Int64Val{
			NilVal: NilVal{
				id:       uuid.New().String(),
				tagName:  tag.Tag_name,
				dataType: tag.DataTypeStr(),
				ts:       time.Now().UnixMilli(),
				qos:      QOS_GOOD,
			},
		}
		return int64Val
	case conf_table_define.UINT8, conf_table_define.UINT16, conf_table_define.UINT32, conf_table_define.UINT64,
		conf_table_define.BIT:
		uint64Val := &Uint64Val{
			NilVal: NilVal{
				id:       uuid.New().String(),
				tagName:  tag.Tag_name,
				dataType: tag.DataTypeStr(),
				ts:       time.Now().UnixMilli(),
				qos:      QOS_GOOD,
			},
		}
		return uint64Val
	case conf_table_define.FLOAT32, conf_table_define.FLOAT64:
		float64Val := &Float64Val{
			NilVal: NilVal{
				id:       uuid.New().String(),
				tagName:  tag.Tag_name,
				dataType: tag.DataTypeStr(),
				ts:       time.Now().UnixMilli(),
				qos:      QOS_GOOD,
			},
		}
		return float64Val
	//case 13:  conf_table_define.STRING
	default:
		stringVal := &StringVal{
			NilVal: NilVal{
				id:       uuid.New().String(),
				tagName:  tag.Tag_name,
				dataType: tag.DataTypeStr(),
				ts:       time.Now().UnixMilli(),
				qos:      QOS_GOOD,
			},
		}
		return stringVal
	}
}

//func NewValObject(bytes []byte, tag *conf_table.TagInfo) ValObject {
//	dataFormat := tag.ToStrDataFormat()
//	switch tag.Data_type {
//	case 0: // 0  位
//		val := &Int64Val{}
//		return binarys.BytesToByte(bytes, dataFormat)
//	case 1: // 1  8位无符号
//		return binarys.BytesToUint8(bytes, dataFormat)
//	case 2: // 2  8位有符号
//		return binarys.BytesToInt8(bytes, dataFormat)
//	case 3: // 3  16位无符号
//		return binarys.BytesToUint16(bytes, dataFormat)
//	case 4: // 4  16位有符号
//		return binarys.BytesToInt16(bytes, dataFormat)
//	case 5: // 5  32位无符号
//		return binarys.BytesToUint32(bytes, dataFormat)
//	case 6: // 6  32位有符号
//		return binarys.BytesToInt32(bytes, dataFormat)
//	case 7: // 7  16位BCD
//		return binarys.BytesToBCD16(bytes, dataFormat)
//	case 8: // 8  32位BCD
//		return binarys.BytesToBCD32(bytes, dataFormat)
//	case 9: // 9  单精度浮点数
//		return binarys.BytesToFloat32(bytes, dataFormat)
//	case 10: // 10 双精度浮点数
//		return binarys.BytesToFloat64(bytes, dataFormat)
//	case 11: // 11 64位无符号
//		return binarys.BytesToUint64(bytes, dataFormat)
//	case 12: // 12 64位有符号
//		return binarys.BytesToInt64(bytes, dataFormat)
//	case 13: // 13 字符串
//		return binarys.BytesToString(bytes)
//	}
//	return 0
//}

//func (receiver *IntVal) SetBytes() {
//	receiver.Val = BytesToTagDataVal(bytes, tag.Data_type, tag.ToStrDataFormat())
//}
